package com.flink.streaming.web.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.Version;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class PyFileCreateUtil {

    static Configuration configuration = null;

    static {
        configuration = new Configuration(new Version("2.3.30"));
        // step1 获取模版路径
        configuration.setClassLoaderForTemplateLoading(PyFileCreateUtil.class.getClassLoader(), "/py/");
    }

    public static File createFile(String fileName, String targetPath, String targetFileName, Map<String, Object> dataMap) throws IOException, TemplateException {

        File docFile;

        Writer out = null;
        try {
            // step2 加载模版文件
            Template template = configuration.getTemplate(fileName);

            // step3 创建路径
            doCreateFilePath(targetPath);

            // step4 生成数据
            docFile = new File(targetPath + targetFileName);

            // step5 创建流
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));

            // step6 输出文件
            template.process(dataMap, out);
        } finally {
            if (out != null) {
                out.close();
            }
        }

        return docFile;
    }


    private static void doCreateFilePath(String path) {
        File file = new File(path);

        if (!file.exists()) {
            file.mkdirs();
        }
    }

    public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws IOException {

        try (ZipOutputStream zos = new ZipOutputStream(out)) {
            File sourceFile = new File(srcDir);
            compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure, 0);
        } catch (Exception e) {
            throw e;
        }

    }

    private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean keepDirStructure, int level) throws IOException {
        byte[] buf = new byte[1024];
        if (sourceFile.isFile()) {
            // 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));

            // copy文件到zip输出流中
            int len;
            FileInputStream in = new FileInputStream(sourceFile);
            while ((len = in.read(buf)) != -1) {
                zos.write(buf, 0, len);
            }

            // Complete the entry
            zos.closeEntry();
            in.close();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
                if (keepDirStructure) {
                    // 空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name + "/"));
                    // 没有文件，不需要文件的copy
                    zos.closeEntry();
                }
            } else {
                for (File file : listFiles) {
                    int current = level;
                    // 判断是否需要保留原来的文件结构
                    if (keepDirStructure) {
                        // 注意：file.getName()前面需要带上父文件夹的名字加一斜杠,
                        // 不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
                        if (level == 0) {
                            compress(file, zos, file.getName(), keepDirStructure, ++current);
                        } else {
                            compress(file, zos, name + "/" + file.getName(), keepDirStructure, ++current);
                        }
                    } else {
                        compress(file, zos, file.getName(), keepDirStructure, ++current);
                    }
                }
            }
        }

    }


    public static void addBaseFile(String resource, String targetPath) throws Exception {
        File targetFile = new File(targetPath + "/main.project");
        targetFile.createNewFile();
        ClassPathResource classPathResource = new ClassPathResource("/py/main.project");
        InputStream inputStream = classPathResource.getInputStream();
        FileCopyUtils.copy(inputStream, new FileOutputStream(targetFile));
        copyFolder(resource + "/com/", targetPath + "/py/");
    }

    /**
     * 复制文件夹
     *
     * @param resource 源路径
     * @param target   目标路径
     */
    public static void copyFolder(String resource, String target) throws Exception {

        File resourceFile = new File(resource);
        if (!resourceFile.exists()) {
            throw new Exception("源目标路径：[" + resource + "] 不存在...");
        }
        File targetFile = new File(target);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }

        // 获取源文件夹下的文件夹或文件
        File[] resourceFiles = resourceFile.listFiles();
        for (File file : resourceFiles) {

            File file1 = new File(targetFile.getAbsolutePath() + File.separator + resourceFile.getName());
            // 复制文件
            if (file.isFile()) {
                // 在 目标文件夹（B） 中 新建 源文件夹（A），然后将文件复制到 A 中
                // 这样 在 B 中 就存在 A
                if (!file1.exists()) {
                    file1.mkdirs();
                }
                File targetFile1 = new File(file1.getAbsolutePath() + File.separator + file.getName());
                FileCopyUtils.copy(file, targetFile1);
            }
            // 复制文件夹
            if (file.isDirectory()) {
                String dir1 = file.getAbsolutePath();
                // 目的文件夹
                String dir2 = file1.getAbsolutePath();
                copyFolder(dir1, dir2);
            }
        }

    }
}
